package com.qingzhuge.file.controller;

import com.qingzhuge.common.HttpCode;
import com.qingzhuge.common.annotation.ASysLogMethod;
import com.qingzhuge.common.annotation.SysLogTypeEnum;
import com.qingzhuge.common.enums.EAuthorityType;
import com.qingzhuge.common.enums.EResourceType;
import com.qingzhuge.controller.base.AbstractController;
import com.qingzhuge.core.annotation.AResource;
import com.qingzhuge.dto.response.ResponseBodyDto;
import com.qingzhuge.file.dto.response.SysFileResponsePkStringDto;
import com.qingzhuge.file.entity.SysFile;
import com.qingzhuge.file.service.ISysFileService;
import com.qingzhuge.file.service.cloud.FileStorageFactory;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

import static com.qingzhuge.common.Constants.Controller.PATH_BY_ID;
import static com.qingzhuge.common.Constants.Controller.PATH_DOWNLOAD;
import static com.qingzhuge.common.Constants.DEFAULT_ENCODING;

/**
 * @author : zero.xiao
 * @description : 文件上传下载控制器
 * @date :2018/8/24 0024 下午 16:46
 * @modified :
 * @since : 1.0.0
 */
@CrossOrigin
public abstract class BaseDownAndloadFileController extends AbstractController {
    private static final Logger log = LoggerFactory.getLogger(BaseDownAndloadFileController.class);
    @Resource
    protected ISysFileService service;

    /**
     * 文件权限类型，用于是否可以匿名下载，0=可匿名下载，1不可匿名下载
     *
     * @return 权限类型
     */
    protected Integer getFileAuthType() {
        return null;
    }


    @ApiOperation(value = "上传")
    @AResource(type = EResourceType.button, authority = EAuthorityType.UPLOAD)
    @ASysLogMethod(type = SysLogTypeEnum.UPDATED)
    @PostMapping("/upload/{module}/{type}")
    @ResponseBody
    public ResponseEntity<ResponseBodyDto<Object>> upload(
            @RequestParam("file") MultipartFile file,
            @PathVariable String module,
            @PathVariable String type
    ) {
        if (null == file || file.isEmpty()) {
            return returnFailed(HttpCode.VALIDATOR_FAILED);
        }
        if (StringUtils.isBlank(module)) {
            module = "qingting";
        }
        //上传文件
        String filename = file.getOriginalFilename();
        if (StringUtils.isEmpty(filename)) {
            filename = request.getParameter("filename");
        }
        String suffix = getSuffix(filename);
        if (StringUtils.isBlank(type)) {
            type = suffix;
        }
        if (StringUtils.isBlank(type)) {
            type = "file";
        }
        String url = Objects.requireNonNull(FileStorageFactory.build()).upload(file, module, type);
        //保存文件信息
        SysFile sysFile = new SysFile();
        sysFile.setUrl(url);
        sysFile.setContentType(file.getContentType());
        sysFile.setLength(file.getSize());
        sysFile.setUid(getUserId());
        sysFile.setSuffix(suffix);
        sysFile.setAuthType(getFileAuthType());
        sysFile.setName(filename);
        service.save(sysFile);
        return returnSuccess(service.bean2Dto(sysFile, SysFileResponsePkStringDto.class));
    }

    private String getSuffix(String filename){
        String suffix = null;
        if (StringUtils.isNotEmpty(filename)) {
            int lastIndexOf = filename.lastIndexOf(".");
            if(lastIndexOf > 0) {
                suffix = Objects.requireNonNull(filename)
                        .substring(lastIndexOf);
            }
        }
        return suffix;
    }

    @ApiOperation("下载")
    @AResource(type = EResourceType.button, authority = EAuthorityType.DOWNLOAD)
    @GetMapping("{module}/{type}/{date}/{name}.{suf}")
    public void download(@PathVariable String module,
                              @PathVariable String type,
                              @PathVariable String date,
                              @PathVariable String name,
                              @PathVariable String suf
    ) {
        String path = "." +
                File.pathSeparator +
                module +
                File.pathSeparator +
                type +
                File.pathSeparator +
                date +
                File.pathSeparator +
                name +
                "." +
                suf;
        try {
            response.addHeader("Content-Disposition", "attachment;filename="
                    + new String(name.getBytes(DEFAULT_ENCODING), StandardCharsets.ISO_8859_1));
            FileStorageFactory.build().download(path, response.getOutputStream());
        } catch (IOException e) {
            log.debug("down file:{}", e.getMessage());
        }
    }

    /**
     * 文件下载
     *
     * @param id 文件id
     */
    @ApiOperation("下载")
    @AResource(type = EResourceType.button, authority = EAuthorityType.DOWNLOAD)
    @GetMapping(PATH_DOWNLOAD)
    public void download(@PathVariable Long id) {
        SysFile sysFile = getFile(id);
        if (null != sysFile) {
            try {
                response.addHeader("Content-Disposition", "attachment;filename="
                        + new String(sysFile.getName().getBytes(DEFAULT_ENCODING), StandardCharsets.ISO_8859_1));
                response.addHeader("Content-Length", String.valueOf(sysFile.getLength()));
                response.setContentType(sysFile.getContentType());
                FileStorageFactory.build().download(sysFile.getUrl(), response.getOutputStream());
            } catch (IOException e) {
                log.debug("down file:{}", e.getMessage());
            }
        }
    }
    /**
     * 文件下载
     *
     * @param id 文件id
     */
    @ApiOperation("文件信息")
    @AResource(type = EResourceType.button, authority = EAuthorityType.DOWNLOAD)
    @GetMapping(PATH_BY_ID)
    public ResponseEntity<ResponseBodyDto<Object>> file(@PathVariable Long id) {
        SysFile sysFile = getFile(id);
        if (null == sysFile){
            return returnFailed("文件不存在");
        }
        return returnSuccess(service.bean2Dto(sysFile, SysFileResponsePkStringDto.class));
    }

    @ApiOperation("删除文件")
    @AResource(type = EResourceType.button, authority = EAuthorityType.DELETE)
    @DeleteMapping(PATH_BY_ID)
    @ResponseBody
    public ResponseEntity<ResponseBodyDto<Object>> delete(@PathVariable Long id) {
        SysFile file = getFile(id);
        if (null != file) {
            FileStorageFactory.build().delete(file.getUrl());
        }
        service.deleteById(id);
        return returnSuccess();
    }

    private SysFile getFile(Long id) {
        SysFile sysFile;
        if (null == getFileAuthType()) {
            sysFile = service.findById(id);
        } else {
            sysFile = service.findByIdAndAuthType(id, getFileAuthType());
        }
        return sysFile;
    }
}